<?php
/**
 * PHPUnit 9.5.28
 */
declare(strict_types=1);

require_once __DIR__ . '/../vendor/autoload.php';

use PHPUnit\Framework\TestCase;
use Cephalopod\Http;

class HttpTest extends TestCase
{
    public function testBuildHttpMessage()
    {
        $data = "Hello here.";
        $result = Http::buildHttpMessage('POST / HTTP/1.1', [
            ['Content-Type', 'plain/text'],
            ['Content-Length', strlen($data)],
        ], $data);
        $trueData = "";
        $trueData .= "POST / HTTP/1.1\r\n";
        $trueData .= "Content-Type: plain/text\r\n";
        $trueData .= "Content-Length: " . strlen($data) . "\r\n";
        $trueData .= "\r\n";
        $trueData .= $data;
        $this->assertEquals($trueData, $result);
    }

    public function testSeparateCanWork()
    {
        $data = "Hello here.";
        $trueData = "";
        $trueData .= "POST / HTTP/1.1\r\n";
        $trueData .= "Content-Type: plain/text\r\n";
        $trueData .= "Content-Length: " . strlen($data) . "\r\n";
        $trueData .= "\r\n";
        $trueData .= $data;
        $result = Http::separate($trueData);
        $this->assertEquals('POST / HTTP/1.1', $result[0]);
        $this->assertEquals([
            ['Content-Type', 'plain/text'],
            ['Content-Length', strlen($data)],
        ], $result[1]);
        $this->assertEquals($data, $result[2]);
        $this->assertEquals('', $result[3]);
        $this->assertTrue($result[4]);
    }

    public function testNoHttpEOLFirstLineIsEmpty()
    {
        $data = 'GET / HTTP/1.1';
        $result = Http::separate($data);
        $this->assertEquals('', $result[0]);
    }

    public function testNoHeaderEnd()
    {
        $trueData = "";
        $trueData .= "POST / HTTP/1.1\r\n";
        $trueData .= "Content-Type: plain/text\r\n";
        $result = Http::separate($trueData);
        $this->assertEquals('POST / HTTP/1.1', $result[0]);
        $this->assertEquals([], $result[1]);
    }

    public function testNoBody()
    {
        $trueData = "";
        $trueData .= "POST / HTTP/1.1\r\n";
        $trueData .= "Content-Type: plain/text\r\n";
        $trueData .= "\r\n";
        $result = Http::separate($trueData);
        $this->assertEquals('POST / HTTP/1.1', $result[0]);
        $this->assertEquals([
            ['Content-Type', 'plain/text'],
        ], $result[1]);
        $this->assertEquals('', $result[2]);
        $this->assertEquals('', $result[3]);
        $this->assertTrue($result[4]);
    }

    public function testHaveUnknowData()
    {
        $trueData = "";
        $trueData .= "POST / HTTP/1.1\r\n";
        $trueData .= "Content-Type: plain/text\r\n";
        $trueData .= "\r\n";
        $trueData .= "GET / HTTP/1.1\r\n";
        $result = Http::separate($trueData);
        $this->assertEquals('POST / HTTP/1.1', $result[0]);
        $this->assertEquals([
            ['Content-Type', 'plain/text'],
        ], $result[1]);
        $this->assertEquals('', $result[2]);
        $this->assertEquals("GET / HTTP/1.1\r\n", $result[3]);
        $this->assertTrue($result[4]);
    }

    public function testParseFirstLine()
    {
        $result = Http::parse("GET http://www.example.com/test HTTP/1.1\r\n");
        $this->assertEquals('GET', $result['method']);
        $this->assertEquals('www.example.com', $result['host']);
        $this->assertEquals(80, $result['port']);
        $result = Http::parse("POST http://www.example.com/test HTTP/1.1\r\n");
        $this->assertEquals('POST', $result['method']);
        $this->assertEquals('www.example.com', $result['host']);
        $this->assertEquals(80, $result['port']);
        $result = Http::parse("HEAD http://www.example.com/test HTTP/1.1\r\n");
        $this->assertEquals('HEAD', $result['method']);
        $this->assertEquals('www.example.com', $result['host']);
        $this->assertEquals(80, $result['port']);
        $result = Http::parse("GET http://www.example.com:9812/test HTTP/1.1\r\n");
        $this->assertEquals('GET', $result['method']);
        $this->assertEquals('www.example.com', $result['host']);
        $this->assertEquals(9812, $result['port']);

        $result = Http::parse("CONNECT www.example.com:9812 HTTP/1.1\r\n");
        $this->assertEquals('CONNECT', $result['method']);
        $this->assertEquals('www.example.com', $result['host']);
        $this->assertEquals(9812, $result['port']);

        $result = Http::parse("CONNECT www.example.com:80 HTTP/1.1\r\n");
        $this->assertEquals('CONNECT', $result['method']);
        $this->assertEquals('www.example.com', $result['host']);
        $this->assertEquals(80, $result['port']);
    }
}
